package utils

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"go_example/src/chatroom/common/message"
	"net"
)

//将这些方法关联到结构体中,传输Transfer
type Transfer struct {
	Conn net.Conn //连接
	Buf [8064]byte //缓冲
}

//将读读取的数据包，直接封装成一个函数readPkg(),返回Message，Error
func (this *Transfer) ReadPkg() (mes message.Message, err error) {
	//buf := make([]byte, 8096)
	//fmt.Println("读取客户端发送的数据")
	//conn.read在没有被关闭的情况下，才会阻塞
	//如果客户端关闭了conn，就不会阻塞了
	_, err = this.Conn.Read(this.Buf[:4])
	if err != nil {
		//err = errors.New("read pkg header error")
		return
	}
	//fmt.Println("读取到buf=", buf[:4])
	//根据读到的buf[:4]，转换成uint32
	var pkgLen uint32
	pkgLen = binary.BigEndian.Uint32(this.Buf[0:4])
	//根据pkgLen读取消息内容
	n, err := this.Conn.Read(this.Buf[:pkgLen])
	if n != (int(pkgLen)) || err != nil {
		//err = errors.New("read pkg body error")
		return
	}
	//将pkgLen反序列化成 message.Message
	err = json.Unmarshal(this.Buf[:pkgLen], &mes)
	if err != nil {
		err = errors.New("ReadPkg() read pkg Unmarshal error")
		return
	}
	return
}

//封装要发送的数据
func (this *Transfer) WritePkg(data []byte) (err error) {
	//发送一个长度给对方
	var pkgLen uint32
	pkgLen = uint32(len(data))
	//var buf [4]byte
	binary.BigEndian.PutUint32(this.Buf[0:4], pkgLen)

	//发送这个长度
	n, err := this.Conn.Write(this.Buf[0:4])
	if n != 4 || err != nil {
		fmt.Println("WritePkg() conn.Write(buf) err=", err)
		return
	}
	//发送消息本身
	n, err = this.Conn.Write(data)
	if n != (int(pkgLen)) || err != nil {
		fmt.Println("WritePkg() conn.Write(data) err=", err)
		return
	}
	return
}
